/**
 * useState:
 *
 *    概念：向组件添加一个 状态变量。
 *         16.8.0 版本之前，函数式组件是叫做无状态组件没有state数据的，在16.8.0开始可以通过
 *         useState 来创建状态数据
 *
 *    语法：
 *      const [state, setState] = useState(initialState);
 *
 *          initialState - 状态的初始值，可以是任意类型
 *          返回值是一个数组
 *          state        - 状态数据的变量名
 *          setState     - 修改该状态数据的一个函数
 *
 *    setState的语法：
 *      1. 直接传递最新的值语法
 *        setState(newState)
 *      2. 传递一个函数的语法
 *        setState((currentState) => newState)
 *      PS: setState 同样是会有合并的特性，如果 newState 依赖于上一次的 state 的话，就推荐使用 函数语法的形式
 *
 *    PS：
 *      1. 可以多次调用
 *      2. 为何 useState 返回值是一个包含两个项目的数组，而不是一个对象呢？
 *
 *         const { state: count, setState: setCount } =  useState(1)
 *         const { state: fruits, setState: setFruits } = useState(["Apple"]);
 *
 *         查看上面的代码，可以知道 返回对象的话，重命名会让代码量变多
 *      3. set 函数是异步的，且没有第二个回调函数的参数
 *      4. 同一周期内，多次 set 会合并成一次调用，为了优化性能
 *      5. 如果 set 函数需要用到最新的 状态数据的话，则推荐使用 函数语法
 */

import { useState } from "react";

function App() {
  /**
   * App 组件第一次渲染的时候，useState 的返回数据是由初始值决定的
   *        后续渲染的时候，  useState 的返回数据是由之前修改决定的
   */
  const [count, setCount] = useState(1);

  const [fruits, setFruits] = useState(["Apple"]);

  const [person, setPerson] = useState({ name: "张三", age: 18 });

  console.log("App Render", count);

  const increment = () => {
    setCount((c) => c + 1);
  };

  const fn1 = () => {
    // setCount(10);

    setCount(count + 1);
    setCount(count + 1);
    setCount(count + 1);
    setCount(count + 1);
    setCount(count + 1);
  };

  const fn2 = () => {
    // setCount(() => 10);

    setCount((count) => count + 1);
    setCount((count) => count + 1);
    setCount((count) => count + 1);
    setCount((count) => count + 1);
    setCount((count) => count + 1);
  };

  const onClick = () => {
    console.log("count", count); // 1

    setCount(2); // 申请使用 2 去重新渲染组件

    console.log("count", count); // 1

    setTimeout(() => {
      console.log("count", count); // 1
    }, 1000);
  };

  return (
    <div>
      <h1>useState</h1>
      <button onClick={increment}>{count}</button>
      <hr />
      <button onClick={fn1}>直接传递newState的方式</button>
      <button onClick={fn2}>函数返回newState的方式</button>
      <hr />
      <button onClick={onClick}>Test</button>

      <hr />
      <button
        onClick={() => {
          // 如下代码不能引起组件重新 Render
          // fruits.push("Orange");
          // setFruits(fruits);

          setFruits([...fruits, "Orange"]);
        }}
      >
        AddFruit
      </button>

      <button
        onClick={() => {
          // 让年龄自增
          //  1. ❌ 不能直接修改 state 数据
          // person.age++;
          //  2. ❌
          // person.age++;
          // setPerson(person);

          setPerson({ ...person, age: person.age + 1 });
        }}
      >
        {person.age}
      </button>
      <hr />

      <ul>
        {fruits.map((item) => (
          <li key={item}>{item}</li>
        ))}
      </ul>
    </div>
  );
}

export default App;
